#pragma once
#include<iostream>
#include"log.hpp"
#include<vector>
#include<queue>
#include<string>
#include<sstream>
#include<pthread.h>

using std::string;
using std::vector;
using std::queue;

const int num=10;   //创建线程池的个数

//代替to_string(gcc4.8对to_string支持不完整)
template<typename T>
std::string to_string_fallback(T value) {
    std::ostringstream oss;
    oss << value;
    return oss.str();
}

struct ThreadInfo
{
    pthread_t tid;
    string name;    
};

template<class T>
class pthreadPool
{
private:
    //辅助函数
    void lock(pthread_mutex_t* mtux)
    {
        pthread_mutex_lock(mtux);
    }

    void unlock(pthread_mutex_t *mtux)
    {
        pthread_mutex_unlock(mtux);
    }

    void wait(pthread_cond_t* cond,pthread_mutex_t* mutex)
    {
        pthread_cond_wait(cond,mutex);
    }

    void signal(pthread_cond_t* cond)
    {
        pthread_cond_signal(cond);
    }

    string getname(pthread_t id)    //获取当前线程的名字
    {
        for(int i=0;i<v_.size();i++)
        {
            if(id==v_[i].tid)
                return v_[i].name;    
        }
            string val;
            val+="名字获取有bug";
            val+=__LINE__;
            return val;
    }

    bool empty()
    {
        return task_.empty();
    }

public:
    T pop()
    {
        T t=task_.front();
        task_.pop();
        return t; 
    }

    void push(const T& t)
    {
        lock(&mutex_);
        if(task_.size()<1000)
            task_.push(t);
        else
            cout<<"当前任务队列大小: "<<task_.size()<<endl;
        signal(&cond_);
        unlock(&mutex_);
    }

    static void* handler(void* argv)    //所有对象都执行当前方法
    {
        pthreadPool<T>* tmp=static_cast<pthreadPool<T>*> (argv);

        while(true)
        {
            tmp->lock(&tmp->mutex_);
            while(tmp->empty()) //循环唤醒线程，避免线程冲突
            {
                tmp->wait(&tmp->cond_,&tmp->mutex_);
            }
            T t=tmp->pop();
            t();
            tmp->unlock(&tmp->mutex_);
            sleep(1);
        }
    } 

    void start()
    {
        int size=v_.size();
        for(int i=0;i<size;i++)
        {
            string name="my name is"+to_string_fallback(v_[i].tid);
            v_[i].name=name;
            pthread_create(&v_[i].tid,nullptr,handler,this);   //创建线程
        }
    }

    static pthreadPool<T>* getInstace()
    {
        if(p_==nullptr)
        {
            // lock(&lock_);    //lock是静态成员函数，不可直接调用
            pthread_mutex_lock(&lock_);
            if(p_==nullptr)
            {
                p_=new pthreadPool<T>();
                cout<<"在堆上申请一块空间"<<endl;                
            }
        }
        return p_;
    }

private:
    pthreadPool()
    :v_(num) //显示构造vector
    {
        pthread_cond_init(&cond_,nullptr);
        pthread_mutex_init(&mutex_,nullptr);
    }

    ~pthreadPool()
    {
        pthread_mutex_destroy(&mutex_);
    }

    //成员变量
    std::vector<ThreadInfo> v_;
    queue<T> task_;

    pthread_mutex_t mutex_; //用来保护任务队列
    pthread_cond_t cond_;

    static pthread_mutex_t lock_;   //保护单例程对象创建（*p_）
    static pthreadPool<T>* p_;

};

//定义静态成员变量
template<class T>
pthreadPool<T>* pthreadPool<T>::p_=nullptr;

template<class T>
pthread_mutex_t pthreadPool<T>::lock_=PTHREAD_MUTEX_INITIALIZER;